﻿using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;
using MLY.Bll;
using MLY.Dal;

namespace MLY
{
  public class File_Parser
  {
    static Dictionary<string, object> newWo;

    enum enumCSVLineState
    {
      FieldStart,
      InQuotedField,
      InField
    }

    public static string[] SplitCSV(string Line, string Delimiter, string TextQualifier)
    {
      enumCSVLineState state = enumCSVLineState.FieldStart;
      bool inQuote = false;
      string letter = "";
      List<string> fields = new List<string>();
      string field = "";

      for (int i = 0; i < Line.Length; i++)
      {
        letter = Line.Substring(i, 1);
        if (state == enumCSVLineState.FieldStart)
        {
          if (letter == Delimiter)
          {
            field = "";
            fields.Add(field);
          }
          else if (letter == TextQualifier)
          {
            state = enumCSVLineState.InQuotedField;
          }
          else
          {
            field += letter;
            state = enumCSVLineState.InField;
          }
        }
        else if (state == enumCSVLineState.InField)
        {
          if (letter == Delimiter)
          {
            fields.Add(field);
            field = "";
            state = enumCSVLineState.FieldStart;
          }
          else
          {
            field += letter;
          }
        }
        else if (state == enumCSVLineState.InQuotedField)
        {
          if (inQuote)
          {
            if (letter == Delimiter)
            {
              fields.Add(field);
              field = "";
              state = enumCSVLineState.FieldStart;
              inQuote = false;
            }
            else if (letter == TextQualifier)
            {
              field += TextQualifier;
              inQuote = false;
            }
            else
            {
              field += letter;
            }
          }
          else
          {
            if (letter == TextQualifier)
            {
              inQuote = true;
            }
            else
            {
              field += letter;
            }
          }
        }
      }
      fields.Add(field);
      return fields.ToArray();
    }

    public static string[] GetCsvHeaders(string csvTxt)
    {
      string[] lines = csvTxt.Split(new string[3] { "\r\n", "\n\r", "\n" }, StringSplitOptions.RemoveEmptyEntries);
      string line = lines[0].Replace("\0", "");
      const string delimiter = ",";
      string textQualifier = '"'.ToString();
      return SplitCSV(line, delimiter, textQualifier);
    }

    public static List<Dictionary<string, object>> ParseCsv(string dat, 
                                                            int? templateId, 
                                                            bool hasHeaders)
    {
      List<Dictionary<string, object>> newWoList = new List<Dictionary<string, object>>();
      string[] lines = dat.Split(new string[3] { "\r\n", "\n\r", "\n" }, StringSplitOptions.RemoveEmptyEntries);//\n
      string[] csvPaths = Utils.csvPaths;
      if (templateId == null)
      {
        for (int j = hasHeaders ? 1 : 0; j < lines.Count(); j++)
        {
          try
          {
            string str = lines[j];
            string[] vals = SplitCSV(str.Replace("\0", ""), ",", '"'.ToString());
            newWo = new Dictionary<string, object>();

            for (int i = 0; i < csvPaths.Length; i++)
            {
              if (i >= vals.Length)
                newWo.Add(csvPaths[i], "null");
              else
              {
                if (vals[i] != "")
                  newWo.Add(csvPaths[i], vals[i]);
                else
                  newWo.Add(csvPaths[i], "null");
              }

            }
            newWoList.Add(newWo);
          }
          catch (Exception ex)
          {
            Log.WriteError("templateId is null", ex);
          }
        }
      }
      else
      {
        List<TableCsvTemplateForUser> TemplateFields = clsCsvTemplate.GetTemplateFields(templateId.Value);
        for (int i = hasHeaders ? 1 : 0; i < lines.Count(); i++)
        {
          try
          {
            string str = lines[i];
            string[] vals = SplitCSV(str.Replace("\0", ""), ",", '"'.ToString());
            newWo = new Dictionary<string, object>();
            for (int j = 0; j < TemplateFields.Count; j++)
            {
              string workOrderFieldName = TemplateFields[j].Lookup_CsvField.CsvField_Name;
              try
              {
                  object value = vals[TemplateFields[j].CsvTemplate_FieldOrder.Value];
                  newWo.Add(workOrderFieldName, value);
              }
              catch (Exception ex1) { Log.WriteError("templateId: " + templateId.ToString(), ex1); }
            }
            newWoList.Add(newWo);
          }
          catch (Exception ex)
          {
            Log.WriteError("templateId: " + templateId.ToString(), ex);
          }
        }
      }
      return newWoList;
    }

    /*public static List<Dictionary<string, object>> parseCsv(StreamReader sr, int? templateId, bool hasHeaders)
    {
      return ParseCsv(sr.ReadToEnd(), templateId, hasHeaders);
    }*/

    public static List<Dictionary<string, object>> ParseXml(StreamReader data)
    {
      List<Dictionary<string, object>> retval = new List<Dictionary<string, object>>();
      XmlDocument doc = new XmlDocument();
      doc.Load(data);
      XmlNodeList nodeList = doc.SelectNodes("/workorders/wo");
      foreach (XmlNode currNode in nodeList)
      {
        newWo = new Dictionary<string, object>();
        foreach (XmlElement currnode in currNode.ChildNodes)
        {
          if (currnode.HasChildNodes)
            newWo.Add(currnode.Name, currnode.FirstChild.Value);
          else
            newWo.Add(currnode.Name, "null");
        }
        retval.Add(newWo);
      }
      return retval;
    }
  }
}
